#include <sw/redis++/redis++.h>
#include <iostream>
#include <fmt/ranges.h>
#include <unordered_set>

using namespace sw::redis;

#define INFOLN(...) std::cout << fmt::format(__VA_ARGS__) << std::endl

int main() {
    ConnectionOptions conn_options;
    conn_options.host = "127.0.0.1";  // Required.
    conn_options.port = 6380; // Optional. The default port is 6379.
    conn_options.password = "bitcoin666";   // Optional. No password by default.

    ConnectionPoolOptions pool_options;
    pool_options.size = 3;  // Pool size, i.e. max number of connections.

    auto redis = Redis(conn_options, pool_options);

    // STRING commands

    if (redis.set("key", "val"))
        std::cout << "OK" << std::endl;
    else
        std::cout << "key does not exist" << std::endl;
    auto val = redis.get("key");
    if (val)
        std::cout << *val << std::endl;
    else
        std::cout << "key not exist" << std::endl;

    // HASH commands

    redis.hset("hash", "field", "val");
    std::unordered_map<std::string, std::string> m = {
            {"field1", "val1"},
            {"field2", "val2"}
    };
    redis.hmset("hash", m.begin(), m.end());

    m.clear();
    redis.hgetall("hash", std::inserter(m, m.begin()));

    INFOLN("{}", m);

    std::vector<OptionalString> vals;
    redis.hmget("hash", {"field1", "field2", "field4"}, std::back_inserter(vals));

    for (const auto &e : vals) {
        if (e)
            INFOLN(*e);
        else
            INFOLN("not exist");
    }

    // SET commands

    redis.sadd("set", "m1");
    std::unordered_set<std::string> set = {"m2", "m3"};
    redis.sadd("set", set.begin(), set.end());
    redis.sadd("set", {"m4", "m5"});

    set.clear();
    redis.smembers("set", std::inserter(set, set.begin()));

    INFOLN("{}", set);

    return 0;
}